package com.sec.android.app.myfiles.module.cloud;

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.widget.Toast;

import com.samsung.android.sdk.slinkcloud.CloudGatewayMediaStore;
import com.sec.android.app.myfiles.R;
import com.sec.android.app.myfiles.feature.CloudMgr;
import com.sec.android.app.myfiles.info.AppConstants;
import com.sec.android.app.myfiles.info.AppConstants.StoragePath;
import com.sec.android.app.myfiles.info.FileType;
import com.sec.android.app.myfiles.log.Log;
import com.sec.android.app.myfiles.module.abstraction.FileRecord;
import com.sec.android.app.myfiles.util.UiUtils;

import java.util.ArrayList;

public class CloudFileRecord extends FileRecord implements Cloneable {
    public static final String CLOUD_ROOT = "root";
    public static final String SEPARATOR = "//";

    String mFileId = null;
    ArrayList<String> mParentIds = new ArrayList<>();
    int mDeviceId = 0;
    String mGoogleDocsLink;
    String mTrashProcessing;

    // For creating record in HomeItem
    public CloudFileRecord(String fullPath) {
        mStorageType = StorageType.Cloud;

        mPath = FileRecord.getPath(fullPath);
        mName = FileRecord.getName(fullPath);
    }

    // For Drag&Drop, MKDIR
    public CloudFileRecord(int deviceId, String parentId, String fileId, String filename) {
        mStorageType = StorageType.Cloud;

        mDeviceId = deviceId;
        mParentIds.add(parentId);
        mFileId = fileId;
        mName = filename;
    }

    // For contextual menu
    public CloudFileRecord(int deviceId, String parentId, String fileId, String fullPath, boolean isFolder) {
        mStorageType = StorageType.Cloud;

        mDeviceId = deviceId;
        mParentIds.add(parentId);
        mFileId = fileId;
        mPath = FileRecord.getPath(fullPath);
        mName = FileRecord.getName(fullPath);
        if (isFolder) {
            mFileType = FileType.FOLDER;
        }
    }

    // For Search, Optimize storage
    public CloudFileRecord(int id, int deviceId, String fileId, String path, String name,
                           long size, long date, int fileType, int isDirectory) {
        mStorageType = StorageType.Cloud;

        mId = id;
        mDeviceId = deviceId;
        mFileId = fileId;
        mPath = path;
        mName = name;
        mSize = size;
        mDate = date;
        mFileType = fileType;
        mIsHidden = isDirectory;
    }

    // For adapter
    public CloudFileRecord(int id, int deviceId, String fileId, ArrayList<String> parentIds, String path, String name, long size, long date,
                           int fileType, int isHidden, int itemCount, int itemCountHidden, String googleDocsLink, String mimeType, String trashProcessing) {
        this(id, deviceId, fileId, parentIds, path, name, size, date, fileType, isHidden, itemCount, itemCountHidden, googleDocsLink, mimeType);

        mTrashProcessing = trashProcessing;
    }

    public CloudFileRecord(int id, int deviceId, String fileId, ArrayList<String> parentIds, String path, String name, long size, long date,
                           int fileType, int isHidden, int itemCount, int itemCountHidden, String googleDocsLink, String mimeType) {
        super(StorageType.Cloud, id, path, name, size, date, fileType, isHidden, itemCount, itemCountHidden);

        mFileId = fileId;
        mDeviceId = deviceId;
        mGoogleDocsLink = googleDocsLink;
        mMimeType = mimeType;

        if (parentIds != null)
            mParentIds.addAll(parentIds);
    }

    @Override
    public String getDisplayName(Context context) {
        String ret = null;
        switch (getCloudType()) {
            case GoogleDrive:
                ret = context.getString(R.string.google_drive);
                break;
            case SamsungDrive:
                ret = context.getString(UiUtils.getSamsungDriveString());
                break;
        }
        return ret;
    }

    @Override
    public boolean isRoot() {
        String fullPath = getFullPath();
        if (fullPath != null) {
            if (fullPath.equalsIgnoreCase(StoragePath.GOOGLE_DRIVE_FOLDER) || fullPath.equalsIgnoreCase(StoragePath.SAMSUNG_DRIVE_FOLDER))
                return true;
        }
        return false;
    }

    @Override
    protected int _getId() {
        return mId;
    }

    public String getFileId() {
        return mFileId;
    }

    public void setFileId(String fileId) {
        mFileId = fileId;
    }

    public int getDeviceId() {
        return mDeviceId;
    }

    public void setDeviceId(int deviceId) {
        mDeviceId = deviceId;
    }

    public String getParentId() {
        String ret = CLOUD_ROOT;
        int size = mParentIds.size();

        if (size > 0) {
            ret = mParentIds.get(size - 1);
        }
        return ret;
    }

    public void setParentId(String parentId) {
        mParentIds.add(parentId);
    }

    public void setParentIds(ArrayList<String> parentIds) {
        mParentIds = parentIds;
    }

    public ArrayList<String> getParentIds() {
        return mParentIds;
    }

    public CloudType getCloudType() {
        CloudType ret = CloudType.None;
        String fullPath = getFullPath();

        if (fullPath != null) {
            if (fullPath.startsWith(StoragePath.GOOGLE_DRIVE_FOLDER)) {
                ret = CloudType.GoogleDrive;
            } else if (fullPath.startsWith(StoragePath.SAMSUNG_DRIVE_FOLDER)) {
                ret = CloudType.SamsungDrive;
            }
        }
        return ret;
    }

    public static CloudType getCloudType(String cloudName) {
        CloudType ret = CloudType.None;

        switch (cloudName) {
            case AppConstants.CloudType.GOOGLE_DRIVE:
                ret = CloudType.GoogleDrive;
                break;
            case AppConstants.CloudType.SAMSUNG_DRIVE:
                ret = CloudType.SamsungDrive;
                break;
        }

        return ret;
    }

    public static String getCloudName(CloudType cloudType) {
        String ret = null;

        switch (cloudType) {
            case GoogleDrive:
                ret = AppConstants.CloudType.GOOGLE_DRIVE;
                break;
            case SamsungDrive:
                ret = AppConstants.CloudType.SAMSUNG_DRIVE;
                break;
        }

        return ret;
    }

    public static int getCloudStringId(CloudType cloudType) {
        int ret = 0;
        switch (cloudType) {
            case GoogleDrive:
                ret = R.string.google_drive;
                break;
            case SamsungDrive:
                ret = UiUtils.getSamsungDriveString();
                break;
            default:
                Log.e("CloudFileRecord", "Not supported cloud");
                break;
        }
        return ret;
    }

    @Override
    protected Uri _getUri(Context context) {
        Log.d(this, "_getUri : devID : " + mDeviceId + ",fileID : " + mFileId);
        int size = mParentIds.size();
        String parentId = null;

        if (size > 0) {
            parentId = mParentIds.get(size - 1);
        } else {
            Log.e(this, "_getUri : parentID is null");
        }
        return Uri.parse(mDeviceId + SEPARATOR + parentId + SEPARATOR + mFileId + SEPARATOR + mName);
    }

    @Override
    public FileRecord getParent() {
        CloudFileRecord ret = null;

        if (!isRoot() && !mParentIds.isEmpty()) {
            try {
                ret = (CloudFileRecord) clone();
                if ((mPath != null) && (!mPath.isEmpty())) {
                    ret.mPath = FileRecord.getPath(mPath);
                    ret.mName = FileRecord.getName(mPath);
                }
                int size = mParentIds.size();
                ret.mFileId = mParentIds.get(size - 1);

                ret.mParentIds = new ArrayList<>();
                ret.mParentIds.addAll(mParentIds);
                ret.mParentIds.remove(size - 1);
            } catch (CloneNotSupportedException e) {
                Log.e(this, "CloneNotSupportedException:" + e.toString());
            }
        }
        return ret;
    }

    public String getGoogleDocsLink() {
        return mGoogleDocsLink;
    }

    public String getTrashProcessing() {
        return mTrashProcessing;
    }

    @Override
    public String getMimeType(Context context) {
        return mMimeType;
    }

    @Override
    public boolean exists(Context context) {
        boolean bRet = false;
        CloudMgr cloudMgr = CloudMgr.getInstance(context);
        if (cloudMgr != null && cloudMgr.isAccountRetrieved(getCloudType())) {
            bRet = (cloudMgr.isSignedIn(getCloudType()) && isRoot()) ? true : exists(context, mName, getParentId());
        } else {
            UiUtils.showToast(context, R.string.retrieving_account);
        }

        return bRet;
    }

    public boolean exists(Context context, String name, String dirId) {
        boolean bRet = false;
        if (dirId != null && name != null) {
            Uri cloudUri = CloudGatewayMediaStore.FileBrowser.FileList2.getFileListUri(getDeviceId(), dirId);
            if (cloudUri != null) {
                final String[] projection = {CloudGatewayMediaStore.FileBrowser.FileBrowserColumns.DISPLAY_NAME};
                String selection = "_display_name_ignore_case =?";
                String[] selectionArgs = new String[]{name};

                Log.d(this, "_exist start");
                try (Cursor cursor = context.getContentResolver().query(cloudUri, projection, selection, selectionArgs, null)) {
                    if (cursor != null) {
                        Log.d(this, "_exists : " + cursor.getCount());
                        if (cursor.getCount() != 0) {
                            bRet = true;
                        }
                    }
                }
            }
        }
        return bRet;
    }

    public boolean existsCheckWhenBack(Context context) {
        boolean bRet = false;
        Uri cloudUri = CloudGatewayMediaStore.CloudFiles.getCloudFileUri(mDeviceId);

        try (Cursor cursor = context.getContentResolver().query(cloudUri, new String[]{"_data"},
                "parent_cloud_id=? and _display_name=?", new String[]{getParentId(), mName}, null)) {
            if ((cursor != null) && (cursor.getCount() != 0)) {
                bRet = true;
            }
        }
        return bRet;
    }

    public boolean isValidRecord(Context context) {
        boolean bRet = true;
        if (!mParentIds.isEmpty()) {
            for (int i = 1; i < mParentIds.size(); i++) {
                String id = mParentIds.get(i);
                Uri cloudUri = CloudGatewayMediaStore.CloudFiles.getCloudFileUri(mDeviceId);
                String selection = "source_media_id" + "=?";
                String[] selectionArgs = new String[]{id};

                try (Cursor cursor = context.getContentResolver().query(cloudUri, null, selection, selectionArgs, null)) {
                    if (cursor == null || cursor.getCount() == 0) {
                        bRet = false;
                        break;
                    }
                }
            }
        }
        return bRet;
    }

    @Override
    public int hashCode() {
        int initValue = 631; // randomly chosen prime numbers
        int constant = 2971; // randomly chosen prime numbers

        int nRet = initValue;
        nRet += mStorageType.hashCode() * constant;
        if (mPath != null) {
            nRet += mPath.hashCode() * constant;
        }
        if (mName != null) {
            nRet += mName.hashCode() * constant;
        }
        if (mFileId != null) {
            nRet += mFileId.hashCode() * constant;
        }
        return nRet;
    }
}
